package com.xyht.medicine_management_system.auth.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xyht.medicine_management_system.auth.entity.ResourceSimpleResp;
import com.xyht.medicine_management_system.auth.util.AuthorizationUtil;
import com.xyht.medicine_management_system.auth.util.JwtTokenUtil;
import com.xyht.medicine_management_system.common.annotation.RepeatRequestCheck;
import com.xyht.medicine_management_system.common.annotation.RequestPass;
import com.xyht.medicine_management_system.common.annotation.VisitorExcludeCheck;
import com.xyht.medicine_management_system.common.annotation.VisitorRequestCheck;
import com.xyht.medicine_management_system.common.commonReturn.CommonCodeEnum;
import com.xyht.medicine_management_system.common.commonReturn.CommonResult;
import com.xyht.medicine_management_system.common.commonReturn.ExceptionCast;
import com.xyht.medicine_management_system.common.util.CacheUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.RequestContext;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Log4j2
public class MyInterceptor implements HandlerInterceptor {
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private AuthorizationUtil authorizationUtil;
    @Autowired
    private CacheUtil cacheUtil;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        log.debug("拦截成功-----------------" + request.getRequestURL());
        String uri1 = request.getRequestURI();
        log.debug("拦截成功-----------------" + uri1);
        boolean isPass = handlerMethod.getMethod().isAnnotationPresent(RequestPass.class);
        if (isPass){
            log.debug("放行+++++++++++++++");
            return true;
        }
        //http的header中获得token
        String token = request.getHeader(tokenHeader);

        //token不存在
        if (token == null || token.equals("")) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.UNAUTHORIZED));
        }
        //验证token
        String authToken = token.substring(tokenHead.length());

        //访客系统独立校验
        boolean excludeBl = handlerMethod.getMethod().isAnnotationPresent(VisitorExcludeCheck.class);
        if (!excludeBl) {
            boolean clazzAnnotationPresent = handlerMethod.getBeanType().isAnnotationPresent(VisitorRequestCheck.class);
            if (clazzAnnotationPresent) {
                boolean bl1 = jwtTokenUtil.validateVisitorToken(authToken);
                if (bl1) {
                    return true;
                } else {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.TOKEN_TIME_OUT));
                }
            }
        }

        boolean bl = jwtTokenUtil.validateToken(authToken);
        if (!bl) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.TOKEN_TIME_OUT));
        }
        //更新token有效时间 (如果需要更新其实就是产生一个新的token)
        String newToken = jwtTokenUtil.refreshHeadToken(authToken);
        if (newToken != null) {
            response.setHeader(tokenHeader, newToken);
        } else {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.UNAUTHORIZED));
        }
        String uri = request.getRequestURI();
        List<ResourceSimpleResp> resList = cacheUtil.getAuthAll();
        if (resList == null || resList.size() < 1) {
//            cacheUtil.saveAllAuth();
        }
        //接口访问权限校验
        resList = cacheUtil.getAuthAll();
        List<ResourceSimpleResp> resultList = resList.stream().filter(res -> res.getUrl().equals(uri)).collect(Collectors.toList());
        if (resultList.size() > 0) {
            String resId = resultList.get(0).getId().toString();
            authorizationUtil.checkUserAuthorization(1, newToken, resId);
        }
        //方法重复校验并保存 含有RepeatRequestCheck注解的直接放行
        RepeatRequestCheck annotationInClass = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(),RepeatRequestCheck.class);
        RepeatRequestCheck annotationMethod = AnnotationUtils.findAnnotation(handlerMethod.getMethod(),RepeatRequestCheck.class);
        if (annotationInClass == null && annotationMethod == null) {
            String methodType = request.getMethod();
            HandlerMethod method = (HandlerMethod) handler;
            String methodName = method.getMethod().getName();
            if (methodType.equals("POST")) {
                String user_id = jwtTokenUtil.getUserIdByRequest(request);
                if (cacheUtil.userCheck(user_id, methodName)) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.REQUEST_REPEAT));
                }
            }
        }
        log.debug("拦截结束-----------------");
        return true;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }

    //判断是否是json结构
    private boolean isJson(String jsonInString) {
        try {
            final ObjectMapper mapper = new ObjectMapper();
            mapper.readTree(jsonInString);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    public Map<String, String> getMultipartParam(HttpServletRequest request) {
        // 获取并解析文件类型和支持最大值
        String maxSize = 2 + "";
        String url = request.getServletContext().getRealPath("/");
        // 上传目录名
        String tempPath = url + "upload" + File.separator + "temp" + File.separator;
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 最大缓存
        factory.setSizeThreshold(5 * 1024);
        // 设置临时文件目录
        factory.setRepository(new File(tempPath));
        ServletFileUpload upload = new ServletFileUpload(factory);
        Map<String, String> result = new HashMap<>();
        if (maxSize != null && !"".equals(maxSize.trim())) {
            // 文件最大上限
            upload.setSizeMax(Integer.valueOf(maxSize) * 1024 * 1024);
        }
        try {
            // 获取所有文件列表
            RequestContext requestContext = new ServletRequestContext(request);
            List<FileItem> items = upload.parseRequest(requestContext);
            for (FileItem item : items) {
                // 如果是文件项，则保存文件到上传目录
                if (!item.isFormField()) {

                    //获取form中参数信息
                } else {
                    // item.getFieldName():获取参数key。item.getString()：获取参数value
                    result.put(item.getFieldName(), item.getString());
                }
            }
        } catch (Exception e) {
            // 提示错误信息
            e.printStackTrace();
            result.put("fileError", "上传失败,文件大小不能超过" + maxSize + "M!");
            return result;
        }
        return result;
    }


}
